package org.jeecg.modules.cascv.image.service.merge;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.HexUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.config.TaskExecutePool;
import org.jeecg.modules.cascv.image.util.HeaderUtil;
import org.jeecg.modules.cascv.image.util.LaptopConstant;
import org.jeecg.modules.cascv.image.util.LaptopUtil;
import org.jeecg.modules.cascv.image.util.NumberUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.imageio.ImageIO;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.MemoryCacheImageInputStream;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicInteger;

@Service
@Slf4j
public class GaoweiguiService extends ImageService {
    @Value("${imageurl}")
    private String imageurl;
    @Autowired
    private TaskExecutePool taskExecutePool;

    @Override
    public String idsNames() {
        return "TGTHYY0501_061H_31_HMRCSAPP2H,6DCDH_1DH";
    }


    @Override
    public Result<Object> merge(JSONObject jsonObject, String idsName, String key) {
        JSONObject conJson = jsonObject.getJSONObject("Content");


        //打印报错不连续的包序号
        String packageNum = conJson.getString(LaptopConstant.Package_number_MAP.get(idsName));
        int intpackageNum = Integer.parseInt(packageNum.split(";")[1]);
        Integer lastPackageNum = LaptopConstant.packageNumMap.get(key);

        if(null==lastPackageNum){
            LaptopConstant.packageNumMap.put(key,intpackageNum);
        }else {
            LaptopConstant.packageNumMap.put(key,intpackageNum);
            if (lastPackageNum + 1 != intpackageNum) {
                if (2511 != lastPackageNum && 0 != intpackageNum) {
                    log.error("图像丢包，包序号不连续，当前包的包序号:"+intpackageNum+"，上一包包序号:"+lastPackageNum);
                }
            }
        }

        String secondStr = jsonObject.getString("second");
        long second = Long.parseLong(secondStr);
        String subSecondStr = jsonObject.getString("subsecond");
        secondStr = LaptopUtil.toDayHoursMinSec(second);
        String frames_field = LaptopConstant.FRAME_FIELD_MAP.get(idsName);
        String dataFrames = conJson.getString(frames_field);
        dataFrames = dataFrames.substring(7, dataFrames.length() - 7);
        StringBuilder queue = LaptopConstant.imageData.get(key);

        //数据不为空，并且数据的长度要小于2006*2并且数据中以指定的后缀结尾
        if (queue != null && queue.length() <= 2006 * 2 && isNeedMergeBehindXuanFu(queue.toString())) {
            //拼接下一个包数据，因为可能是断开的。
            dataFrames = queue.toString() + dataFrames;
            boolean checkStart = false;
            //判断dataFrames是否包含180000
            if (dataFrames.contains(LaptopConstant.GAOWEIGUI_XUANFU_HEADER)) {
                //得到180000的位置，截取dataFrames从headerIndex + 26 到 headerIndex + 32
                int headerIndex = dataFrames.indexOf(LaptopConstant.GAOWEIGUI_XUANFU_HEADER) - 2; //从头开始查找指定字符串的位置，查到了就返回位置的开始索引（从0开始），如果查不到，就返回-1
                String secondHeader = StringUtils.substring(dataFrames, headerIndex + 26, headerIndex + 32);
                //判断secondHeader是否等于 180002
                if (secondHeader.equals(LaptopConstant.GAOWEIGUI_XUANFU_HEADER_SECOND_CAN)) {
                    checkStart = true;
                    String imageSizeStr = dataFrames.substring(headerIndex + 6, headerIndex + 14);
                    int imageSize = NumberUtil.versbyte2Integer(HexUtil.decodeHex(imageSizeStr), 0);
                    int canNum = Double.valueOf(Math.ceil((imageSize) / 8.0)).intValue() + 4;
                    Integer packageTotalNum = Double.valueOf(Math.ceil((canNum * 12 - (1996 * 2 - headerIndex) / 2) / 1996.0)).intValue() + 1;
                    System.out.println("1canNUm=" + canNum);
                    System.out.println("1packageTotalNum=" + packageTotalNum);
                    LaptopConstant.packageTotalNum.put(key, new AtomicInteger(packageTotalNum));
                }
            }

            if (checkStart) {
                queue = new StringBuilder();
                LaptopConstant.imageData.put(key, queue);
                LaptopConstant.packageTotalNum.get(key).addAndGet(-1);
                queue.append(dataFrames);
            } else {
                LaptopConstant.imageData.remove(key);
            }
            return null;
        }

        //高微柜拼图
        if (dataFrames.contains(LaptopConstant.GAOWEIGUI_XUANFU_HEADER)) { //用来判断一个子串是否存在 180000
            int headerIndex = dataFrames.indexOf(LaptopConstant.GAOWEIGUI_XUANFU_HEADER) - 2;
            String secondHeader = StringUtils.substring(dataFrames, headerIndex + 26, headerIndex + 32);
            if (secondHeader.equals(LaptopConstant.GAOWEIGUI_XUANFU_HEADER_SECOND_CAN)) { //180002
                String imageSizeStr = dataFrames.substring(headerIndex + 8, headerIndex + 16);
                int imageSize = NumberUtil.versbyte2Integer(HexUtil.decodeHex(imageSizeStr), 0);
                int canNum = Double.valueOf(Math.ceil((imageSize) / 8.0)).intValue() + 4;
                Integer packageTotalNum = Double.valueOf(Math.ceil((canNum * 12 - (1996 * 2 - headerIndex) / 2) / 1996.0)).intValue() + 1;
                System.out.println("canNUm=" + canNum);
                System.out.println("packageTotalNum=" + packageTotalNum);
                LaptopConstant.packageTotalNum.put(key, new AtomicInteger(packageTotalNum));
                queue = new StringBuilder();
                LaptopConstant.imageData.put(key, queue);
                int num = LaptopConstant.packageTotalNum.get(key).addAndGet(-1);  //获取-1后的值 先-1
                System.out.println("num=" + num);
                queue.append(dataFrames);
                return null;
            }
        }

        if (isNeedMergeBehindXuanFu(dataFrames) && queue == null) {
            queue = new StringBuilder();
            LaptopConstant.imageData.put(key, queue);
            queue.append(dataFrames);
            return null;
        } else if (queue != null) {
            queue.append(dataFrames);
            int num = LaptopConstant.packageTotalNum.get(key).addAndGet(-1);
            System.out.println("num=" + num);
            if (num <= 0) {
                if (queue.length() > 2006 * 2) {
                    try {
                        gaoweiguiComposite(queue, conJson, idsName, key, secondStr, subSecondStr);
                    } catch (Exception e) {
                        e.printStackTrace();
                        log.error("合成图片失败", e);
                    }
                    queue = null;
                    LaptopConstant.packageTotalNum.remove(key);
                    LaptopConstant.imageData.remove(key);
                    merge(jsonObject, idsName, key);
                }
            }
            return null;
        }
        return null;
    }

    private static boolean isGaoweiguiHeader(String dataFrames, int headerIndex) {
        if (dataFrames.contains(LaptopConstant.GAOWEIGUI_XUANFU_HEADER)) {
            String secondHeader = StringUtils.substring(dataFrames, headerIndex + 18, headerIndex + 32);
            if (secondHeader.contains(LaptopConstant.GAOWEIGUI_XUANFU_HEADER_SECOND_CAN)) {
                return true;
            }
        }
        return false;
    }

    private boolean gaoweiguiComposite(StringBuilder sb, JSONObject content, String idsName, String key, String secondStr, String subSecondStr) {
        String headerStr = null;
        boolean removeHeader = false;
        boolean removePre = false;
        int headerIndex = sb.indexOf(LaptopConstant.GAOWEIGUI_XUANFU_HEADER);
        String imageSizeStr = sb.substring(headerIndex + 6, headerIndex + 14);
        int imageSize = NumberUtil.versbyte2Integer(HexUtil.decodeHex(imageSizeStr), 0);

        headerIndex -= 2;

        sb = sb.delete(0, headerIndex);
        headerStr = sb.substring(0, 48);
        Map<String, String> headerMap = HeaderUtil.parseGaowengui(headerStr);
        sb = sb.delete(0, 48);

        int oneCanSize = 12 * 2;
        int headerSize = 8;

        ByteBuffer byteBuf = ByteBuffer.allocateDirect(imageSize);
        int writeIndex = 0;

        int n = 0;
        while (true) {
            if (sb.length() < oneCanSize) {
                break;
            }
            String oneCanStr = sb.substring(0, oneCanSize);
            //拿到oneCanStr后，将其从sb中删除
            sb.delete(0, oneCanSize);
//            System.out.println(oneCanStr);

            byte[] bytes = HexUtil.decodeHex(oneCanStr.substring(headerSize));
            int writeLen = bytes.length;
            if (writeIndex + writeLen > imageSize) {
                writeLen = imageSize - writeIndex;
                byteBuf.put(ArrayUtil.sub(bytes, 0, writeLen));
            } else {
                byteBuf.put(bytes);
            }
            writeIndex += writeLen;
//            System.out.println(n++ + "add=" + writeIndex);
            if (writeIndex > imageSize) {
                break;
            }
        }

        if (writeIndex < imageSize) {
            String oneCanStr = sb.substring(headerSize, (imageSize - writeIndex) * 2 + headerSize);
            byte[] bytes = HexUtil.decodeHex(oneCanStr);
            byteBuf.put(bytes);
        }
        CompletableFuture<JSONObject> future = CompletableFuture.supplyAsync(() -> {
            long start = System.currentTimeMillis();
            byteBuf.flip();
                byte[] arr = new byte[imageSize];
                if (byteBuf.limit() < imageSize) {
                    System.out.println("len error");
                }
                byteBuf.get(arr);

                String idStr = IdWorker.getIdStr();
                //  FileUtil.touch("/data/"+idStr+".jpg");
                //  LaptopConstant.nativeImageIO.memWriteAndScale(arr,"D:\\data\\",idStr+".jpg","jpg",0.5);
                //   FileUtil.writeBytes(arr, "/data/"+idStr+".jpg");


                File imagefile = FileUtil.touch("/data/images/" + idStr + ".jpg");

//        FileUtil.writeUtf8String(HexUtil.encodeHexStr(array), "d://" + imageSaveName + ".txt");
                try {
                    FileUtil.writeBytes(arr, "/data/images/" + idStr + ".jpg");
                } catch (Exception e) {
                    log.error("高微柜生成图片失败," + e);
                }

                int width = 1280;
                int height = 1024;

                BufferedImage bi = null;
                try {
                    bi = ImageIO.read(imagefile);
                    width = bi.getWidth();
                    height = bi.getHeight();
                } catch (Exception e) {
                    log.error("获取高微柜图片信息失败" + e);
                }


                //String base64 = Base64.getEncoder().encodeToString(arr);

                String imageUrl = "http://" + imageurl + "/jeecg-boot/test/gmvVideo/getImage/" + idStr + ".jpg";
                System.out.println("imageUrl = " + imageUrl);
                content.put("imageUrl", imageUrl);
                // content.put("imageBase64", base64);
                content.put("idsName", idsName);
                //   String secondStr = content.getString(LaptopConstant.SECOND_FIELD_MAP.get(idsName)).split(";")[1];
                //   String subSecondStr = content.getString(LaptopConstant.SUB_SECOND_FIELD_MAP.get(idsName)).split(";")[1];
                String[] split = secondStr.split(":");
                content.put("ts", split[0] + "天" + split[1] + "时" + split[2] + "分" + split[3] + "秒" + subSecondStr + "微秒");
                //content.put("fileId", key);
                content.remove(LaptopConstant.FRAME_FIELD_MAP.get(idsName));
            content.put("key", key);
            log.info("高温柜"+idsName+"合成一张图片消耗时间：" + (System.currentTimeMillis() - start) + "毫秒");

            return content;
        },taskExecutePool.threadPoolTaskExecutor2());
        LaptopConstant.imageFutureList.add(future);

        return true;
    }

    private boolean isNeedMergeBehindXuanFu(String dataFrames) {
        return dataFrames.endsWith(LaptopConstant.GAOWEIGUI_XUANFU_HEADER_START_SUB_1) //测试字符串是否以指定的后缀结束 是返回true
                || dataFrames.endsWith(LaptopConstant.GAOWEIGUI_XUANFU_HEADER_START_SUB_2);
    }

    public static void main(String[] args) {
//        System.load("D:/disk1/libjpeg-9.dll");
//        System.load("D:/disk1/libpng-3.dll");
//        System.load("D:/disk1/NativeImageIOJNI.dll");
        //按行处理文件内容，编码为UTF-8
        List<String> strings = FileUtil.readUtf8Lines("D:\\pc_workspace\\gaoweigui2\\TGTHYY0501_061H_31_HMRCSAPP2H_2.txt");
        GaoweiguiService test = new GaoweiguiService();
        for (String string : strings) {
            JSONObject jsonObject = JSONObject.parseObject(string);
            test.merge(jsonObject, "TGTHYY0501_061H_31_HMRCSAPP2H", "TGTHYY0501_061H_31_HMRCSAPP2H");

        }
    }

}
